import * as THREE from "./threejs/three.module.js";
//计算指定faceIdx面上的点拉伸，即有点p1点拉伸到p2点，坐标的变化情况  dis2 = dx2+dy2+dz2
export function getChangedPoints(points,faceIdx,p1,p2){
    // 底面             顶面         前面          后面         左面         右面
    //     0             1            2            3            4           5
    //[0, 1, 2, 3], [4, 5, 6, 7],[0, 1, 5, 4],[2, 3, 7, 6],[0, 3, 7, 4],[1, 2, 6, 5] 
    //0   1  2  3    4  5  6  7   8  9  10 11 12  13 14 15 16 17 18 20  21  22 23 24 
    //入参检查
    if(!isArray(points) || !isPoint(p1) || !isPoint(p2)){
        return;
    }
    if(!isNum(faceIdx) || faceIdx<0 || faceIdx>5){
        console.log('[getChangedPoints]计算指定faceIdx面上的点拉伸,面序号只能在[0..5],当前为[',faceIdx,']');
        return;
    }
    var dx = accSub(p2.x,p1.x);
    var dy = accSub(p2.y,p1.y);
    var dz = accSub(p2.z,p1.z); //dz>0往上拉

    
}
//空间点p到两点p1,p2直线的垂足 
//https://blog.csdn.net/zhouschina/article/details/14647587
export function getFootOfPerpendicular(p0,p1,p2){
  if(!isPoint(p0) || !isPoint(p1) || !isPoint(p2)){
    return null;
  }
  var dx = accSub(p1.x , p2.x);
  var dy = accSub(p1.y , p2.y);
  var dz = accSub(p1.z , p2.z);
  if(Math.abs(dx)<0.000001 && Math.abs(dy)<0.000001 && Math.abs(dz)<0.000001){
    return p1;
  }
  // double u = (pt.x - begin.x)*(begin.x - end.x) 
  // + (pt.y - begin.y)*(begin.y - end.y) 
  // + (pt.z - begin.z)*(begin.z - end.z);
  var u1 = differenceProduct(p0.x, p1.x,p1.x, p2.x);
  var u2 = differenceProduct(p0.y, p1.y,p1.y, p2.y);
  var u3 = differenceProduct(p0.z, p1.z,p1.z, p2.z);
  var u12 = accAdd(u1,u2);
  var u   = accAdd(u12,u3);
  //u = u/((dx*dx)+(dy*dy)+(dz*dz));
  var ddxyz = powSum2(dx,dy,dz);
  var uu = accDiv(u,ddxyz);
  var rx = accMul(uu,dx);
  var ry = accMul(uu,dy);
  var rz = accMul(uu,dz);
  rx = accAdd(rx,p1.x)
  ry = accAdd(ry,p1.y)
  rz = accAdd(rz,p1.z)
  var result = {x:rx,y:ry,z:rz}
  return result
}

//已知AB两点坐标，使得实数λ使得λAB = AC，求C点坐标
export function getLambdaPoint(p1,p2,lambda){
  var dx = accSub(p1.x , p2.x);
  var dy = accSub(p1.y , p2.y);
  var dz = accSub(p1.z , p2.z);
  dx = accMul(dx,lambda)
  dy = accMul(dy,lambda)
  dz = accMul(dz,lambda)
  var rx = accAdd(p1.x,dx);
  var ry = accAdd(p1.y,dy);
  var rz = accAdd(p1.z,dz);
  var result = {x:rx,y:ry,z:rz}
  return result
}
//差积 (a-b)*(c-d) 
export function differenceProduct(a,b,c,d){
  var ab  = accSub(a,b);
  var cd  = accSub(c,d);
  var result = accMul(ab,cd);
  return result
}
//平方和 a*2+ b*b + c*c 
export function powSum2(a,b,c){
  if(!isNum(a)){
    a = 0;
  }
  if(!isNum(b)){
    b = 0;
  }
  if(!isNum(c)){
    c = 0;
  }
  var sa = Math.pow(a,2);
  var sb = Math.pow(b,2);
  var sc = Math.pow(c,2);
  var sab = accAdd(sa,sb);
  var result = accAdd(sab,sc);
  return result;
}

//从数组从取得值对象
export function getObjectByIndex(arr,idx) {
  if(!isArray(arr) && !isNum(idx)){
      return null;
  }
  var len = arr.length;
  if(idx<0 || idx>=len){
    return null;
  }
  return arr[idx];
}

//判断对象实例是否不为空间点，即点为null 或者坐标能为空或者坐标不为数字
export function pointToStr  (point) {
  if(null==point || typeof(point)=="undefined"){
      return "";
  }
  var result = '';
  if(isNum(point.x)){
    if(''!==result){
      result += ',';
    }
    result += 'x:'+point.x;
  }
  if(isNum(point.y)){
    if(''!==result){
      result += ',';
    }
    result += 'y:'+point.y;
  }
  if(isNum(point.z)){
    if(''!==result){
      result += ',';
    }
    result += 'z:'+point.z;
  }
  if(''!==result){
    result = '{'+result+'}';
  }
  return result;
}

//判断对象实例是否不为空间点，即点为null 或者坐标能为空或者坐标不为数字
export function isPoint  (point) {
    if(null==point || typeof(point)=="undefined"){
        return false;
    }
    if(isNum(point.x) && isNum(point.y) && isNum(point.z)){
        return true;
    }
    return false;
}
//判断对象实例是否为空
export function isEmpty  (obj) {
    if(null==obj || typeof(obj)=="undefined"){
        return true;
    }
    return false;
}
//判断对象是否为数字
export function isNum (obj) {
    if(null==obj || typeof(obj)=="undefined" || isNaN(obj)){
        return false;
    }
    if(typeof(obj)=='number'){
        return true;
    }
    return false;
}
//判断对象是否为数组
export function isArray (obj) {
    if(null==obj || typeof(obj)=="undefined" || isNaN(obj)){
        return false;
    }
    if(obj instanceof Array){
        return true;
    }
    return false;
}

//创建拖动的标志物
export function createDragMarker  (hScene,opt) {
    if(null==opt || typeof(opt)=="undefined"){
        opt = {}
    }
    const geometry = new THREE.SphereGeometry( 3, 32, 16 );
    const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
    var dragMarker =  new THREE.Mesh( geometry, material )
    dragMarker.visible = false;
    dragMarker.userData = opt
    hScene.add(dragMarker);
    return dragMarker;
}

//设置标记物的位置
export function getMessPosition(hMess){
  if(isEmpty(hMess)){
    return null;
  }
  var hPosition = null;
  try{
    hPosition= hMess.position;
  }catch(ex){

  }
  try{
    if(isEmpty(hPosition) && !isEmpty(hMess.object)){
      hPosition = hMess.object.position;
    }
  }catch(ex){
  
  }
  if(isEmpty(hPosition)){
    return null;
  }
  var position = {}
  position.x = hPosition.x;
  position.y = hPosition.y;
  position.z = hPosition.z;
  return position;  
}
//设置标记物的位置
export function setMarkerPoint(hMarkers,iIdx,point){
    if(null==hMarkers || typeof(hMarkers)=="undefined" || !(hMarkers instanceof Array)){
        return;
    }
    if(null==point || typeof(point)=="undefined"){
        return;
    }
    if(null==iIdx || typeof(iIdx)!="number"){
        return;
    }
    var iSize = hMarkers.length;
    if(iIdx<0 || iIdx>=iSize){
        return;
    }

    var hMarker = hMarkers[iIdx]
    // 设置物体的位置
    hMarker.position.set(point.x, point.y, point.z);
    hMarker.visible = true
}
      
//取得模型的类别
export function getMessType(hMess){
    var hGeometry = getMessGeometry(hMess);
    if(null==hGeometry || typeof(hGeometry)=="undefined"){
      return null;
    }
    return hGeometry.type;
  }

//取得模型[hMess]指定面[faceIdx]的点 , points可以回传模型的所有顶点  底面[0, 1, 2, 3] 顶面 [4, 5, 6, 7]
export function getMessFacePoints(hMess,faceIdx,points){
    if(null==hMess || typeof(hMess)=="undefined"){
      return;
    }
    if(null==faceIdx || typeof(faceIdx)!="number" || faceIdx<0 || faceIdx>=6){
      faceIdx = 0;
    }
    if(null==points || !(points instanceof Array) || points.length<1){
      points = getMessPoints(hMess);
    }
    if(null==points || !(points instanceof Array) || points.length<8){
      return null;
    }
    const faces = [
          [0, 1, 2, 3],// 底面            
          [4, 5, 6, 7],// 顶面            
          [0, 1, 5, 4],// 前面            
          [2, 3, 7, 6],// 后面            
          [0, 3, 7, 4],// 左面            
          [1, 2, 6, 5] // 右面
      ]; 
    var idxs = faces[faceIdx];
    var result = [];
    var point;
    idxs.forEach(idx => {
              point = points[idx]
              result.push(point);
          });
    return result;
  }

  //取得模型指定面的点
  export function getMessVertexs(hMess){
    if(null==hMess || typeof(hMess)=="undefined"){
      return null;
    }
    if(null==hMess.object || typeof(hMess.object)=="undefined"){
      return null;
    }
    if(null==hMess.object.geometry || typeof(hMess.object.geometry)=="undefined"){
      return null;
    }
    if(null==hMess.object.geometry || typeof(hMess.object.geometry)=="undefined"){
      return null;
    }
    if(null==hMess.object.geometry.attributes || typeof(hMess.object.geometry.attributes)=="undefined"){
      return null;
    }
    if(null==hMess.object.geometry.attributes.position || typeof(hMess.object.geometry.attributes.position)=="undefined"){
      return null;
    }
    return hMess.object.geometry.attributes.position.array;
  }

//取得顶点中心点
export function getCenterPoint(points){
    if(null==points || !(points instanceof Array)){
      return null;
    }
    var iSize = points.length;
    var point;
    var iSum = 0;
    var xSum = 0;
    var ySum = 0;
    var zSum = 0;
    for(var iIdx=0;iIdx<iSize;iIdx++){
      point = points[iIdx];
      if(null==point){
        continue;
      }
      iSum ++;
      xSum = accAdd(xSum,point.x);
      ySum = accAdd(ySum,point.y);
      zSum = accAdd(zSum,point.z);
    }
    if(iSum<1){
      return null;
    }
    xSum = accDiv(xSum,iSum);
    ySum = accDiv(ySum,iSum);
    zSum = accDiv(zSum,iSum);
    return {x:xSum,y:ySum,z:zSum};
  }

//取得模型的类别
export function getMessGeometry(hMess){
    if(null==hMess || typeof(hMess)=="undefined"){
      return null;
    }
    var hGeometry = null;
    try{
      hGeometry = hMess.geometry;
    }catch(ex){
      hGeometry = null;
    }
    if(null==hGeometry || typeof(hGeometry)=="undefined"){
      if(null==hMess.object || typeof(hMess.object)=="undefined"){
        return null;
      }
      try{
        hGeometry = hMess.object.geometry;
      }catch(ex){
        hGeometry = null;
      }        
    }
    return hGeometry;
  }

//将三维坐标转为字符串
export function vertexsToStr(vertexs){
    if(null==vertexs || typeof(vertexs)=="undefined"){
      return '';
    }
    var iSize = vertexs.length/3;
    var result = '';
    var x,y,z;
    for(var i=0;i<iSize;i++){
      x = vertexs[i*3];
      y = vertexs[i*3+1];
      z = vertexs[i*3+2];
      result += '{x:'+x+','+'y:'+y+',z:'+z+'}';
    }
    return result;
  }

//取得模型指定面的点
export function getMessPoints(hMess){
    var vertexs = getMessVertexs(hMess);
    if(null==vertexs || !(vertexs instanceof Float32Array)){
      return null;
    }
    var point
    var result = [];
    for(var i=0;i<8;i++){
      point = vertexToPoint(vertexs,i);
      if(null==point){
        continue;
      }
      result.push(point);
    }
    return result;
  }
  //取得三维中的Vertice坐标转变为点坐标
  export function vertexToPoint(vertexs,pointIdx){
    if(null==pointIdx || typeof(pointIdx)!="number"){
      return null;
    }
    if(null==vertexs || typeof(vertexs)=="undefined" || !(vertexs instanceof Float32Array)){
      return null;
    }
    var xIdx = pointIdx*3;
    var yIdx = xIdx + 1;
    var zIdx = xIdx + 2;
    var iSize = vertexs.length;
    if(zIdx>=iSize || zIdx<2){
      return null;
    }
    var x = vertexs[xIdx];
    var y = vertexs[yIdx];
    var z = vertexs[zIdx];
    return {x:x,y:y,z:z}
  }

//高精度计算
// 两个浮点数求和
export function accAdd(num1,num2){
    var r1,r2,m;
    try{
        r1 = num1.toString().split('.')[1].length;
    }catch(e){
        r1 = 0;
    }
    try{
        r2=num2.toString().split(".")[1].length;
    }catch(e){
        r2=0;
    }
    m = Math.pow(10,Math.max(r1,r2));
    // return (num1*m+num2*m)/m;
    return Math.round(num1*m+num2*m)/m;
}
// 两个浮点数相减
export  function accSub(num1,num2){
    var r1,r2,m,n;
    try{
        r1 = num1.toString().split('.')[1].length;
    }catch(e){
        r1 = 0;
    }
    try{
        r2=num2.toString().split(".")[1].length;
    }catch(e){
        r2=0;
    }
    m = Math.pow(10,Math.max(r1,r2));
    n =(r1>=r2)?r1:r2;
    return (Math.round(num1*m-num2*m)/m).toFixed(n);
}
// 两数相乘
export  function accMul(num1,num2){
    var m=0,s1=num1.toString(),s2=num2.toString(); 
    try{m+=s1.split(".")[1].length}catch(e){};
    try{m+=s2.split(".")[1].length}catch(e){};
    return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);
}
// 两数相除
export  function accDiv(num1,num2){
    var t1,t2,r1,r2;
    try{
        t1 = num1.toString().split('.')[1].length;
    }catch(e){
        t1 = 0;
    }
    try{
        t2=num2.toString().split(".")[1].length;
    }catch(e){
        t2=0;
    }
    r1=Number(num1.toString().replace(".",""));
    r2=Number(num2.toString().replace(".",""));
    return (r1/r2)*Math.pow(10,t2-t1);
}